/**
 * @author	Yitzchak Arad
 * @project	VIA, an EXE infector virus
 * @date	2011
 */

#include "dbg.h"

#include <Windows.h>
#include <stdio.h>
#include <stdarg.h>

// debug traces are defined only under DEBUG configuration
// is RELASE (NDEBUG) the function is defined to do nothing

#if defined(_DEBUG) || defined(LOGS_IN_RELEASE)

#define MAX_TRACE_SIZE (1024)

// extern as C code, so pure C code can use the functionality.
extern "C" {

void _cdecl traceDbg(const wchar_t* fmt, ...)
{
	wchar_t msg[MAX_TRACE_SIZE] = {0};

	// send the tail of var-args list to the appropriate API function
	va_list vl;
	va_start(vl, fmt);
	_vswprintf_p(msg, MAX_TRACE_SIZE, fmt, vl);

	OutputDebugStringW(msg);
	appendLineIntoUnicodeTextFile(L"%SystemDrive%\\viaLog.txt", msg);
}

void appendLineIntoUnicodeTextFile(const wchar_t* filename, const wchar_t* line)
{
	// system special directories (such as %windir%, etc.) should be expanded
	wchar_t expandedFilename[MAX_PATH] = {0};
	ExpandEnvironmentStringsW(filename, expandedFilename, MAX_PATH);
	
	// open the file using FILE_APPEND_DATA as desired-access, and OPEN_ALWAYS as creation-disposition
	HANDLE hFile = CreateFileW(expandedFilename, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0);
	if( INVALID_HANDLE_VALUE == hFile )
	{
		// failed opening the debug file, can't tell anyone :(
		return;
	}

	
	DWORD dwFileSize = GetFileSize(hFile, NULL);
	DWORD dwNumOfBytesWritten = 0;

	// File has already existed. just go to its end.
	if( dwFileSize > 0 )
	{
		SetFilePointer(hFile, 0, 0, FILE_END);
	}

	// The file is new. we have to write the two bytes of UNICODE_PREFIX to its beginning
	else
	{
		byte UNICODE_PREFIX[] = {0xff, 0xfe};
		WriteFile(hFile, UNICODE_PREFIX, sizeof(UNICODE_PREFIX), &dwNumOfBytesWritten, NULL);
	}

	// write the debug message
	WriteFile(hFile, line, wcslen(line) * sizeof(wchar_t), &dwNumOfBytesWritten, NULL);

	// write a line break ("\r\n");
	byte LINE_BREAK[] = {0x0d, 0x00, 0x0a, 0x00};
	WriteFile(hFile, LINE_BREAK, sizeof(LINE_BREAK), &dwNumOfBytesWritten, NULL);

	// release file handle
	CloseHandle(hFile);
}

}; // extern C

#else // NDEBUG

void traceDbg(wchar_t* fmt, ...)
{

}

#endif // _DEBUG